﻿using System;
using System.Linq;
using System.Collections.Generic;

using SimbaRGVMonitor.Common.Data;

namespace SimbaRGVMonitor.Models
{
    abstract class ModelCollection<TKey, TValue> : ReadOnlyDictionary<TKey, TValue>
    {
        public event EventHandler<ModelEventArgs<TKey, TValue>> ModelAdded;
        private void OnModelAddedEventArgs(TKey key, TValue value)
        {
            var e = new ModelEventArgs<TKey, TValue>(key, value);
            ModelAdded.TriggerEvent(this, e);
        }

        public event EventHandler<ModelEventArgs<TKey, TValue>> ModelUpdated;
        private void OnModelUpdatedEventArgs(TKey key, TValue value)
        {
            var e = new ModelEventArgs<TKey, TValue>(key, value);
            ModelUpdated.TriggerEvent(this, e);
        }

        public event EventHandler<ModelEventArgs<TKey, TValue>> ModelRemoved;
        private void OnModelRemovedEventArgs(TKey key, TValue value)
        {
            var e = new ModelEventArgs<TKey, TValue>(key, value);
            ModelRemoved.TriggerEvent(this, e);
        }

        //====================================================================================================
        //以上是类型事件及触发函数
        //----------------------------------------------------------------------------------------------------
        //以下是集合添加、删除及更新
        //====================================================================================================

        public void Add(TKey key, TValue value)
        {
            AddCore(key, value);

            OnModelAddedEventArgs(key, value);
        }

        public bool Remove(TKey key, TValue value)
        {
            var success = RemoveCore(key);
            if(success)
            {
                OnModelRemovedEventArgs(key, value);
            }
            return success;
        }

        public void Update(TKey key, TValue value)
        {
            TValue current;
            if(TryGetValue(key, out current) &&
               current.Equals(value) == false)
            {
                AddOrUpdateCore(key, value);
                OnModelUpdatedEventArgs(key, value);
            }
        }

        public void Update(Dictionary<TKey, TValue> newItems)
        {
            RunWithContainer(currentItems => UpdateCore(currentItems, newItems));
        }

        protected virtual void UpdateCore(Dictionary<TKey, TValue> currentItems, Dictionary<TKey, TValue> newItems)
        {
            var addList = newItems.Keys.Except(currentItems.Keys).ToArray();
            var updateList = newItems.Keys.Intersect(currentItems.Keys).ToArray();
            var removeList = currentItems.Keys.Except(newItems.Keys).ToArray();

            foreach(var key in addList)
            {
                var value = newItems[key];
                Add(key, value);
            }

            foreach(var key in updateList)
            {
                var value = newItems[key];
                Update(key, value);
            }

            foreach(var key in removeList)
            {
                var value = currentItems[key];
                Remove(key, value);
            }
        }
    }
}
